package com.print.androidprintproject.print;

import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Matrix;
import android.graphics.Paint;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.util.Log;
import com.print.androidprintproject.MainActivity;
import com.print.printlib.export.MessageConst;
import com.print.printlib.export.PrintApis;
import com.print.printlib.export.errorCodes;
import com.print.printlib.export.preDefiniation;

import java.util.ArrayList;

public class PrintJobService implements Runnable {
    private PrintApis printApis;
    private int objId;
    private static final String ENCODE = "gb2312";
    private static PrintJobService printJobService = null;

    private Object waitObject;
    private String printName;
    Object printPort;
    private Handler handler;
    private COMMAND_TYPE commandType;
    private Object[] params;
    private long waitTimeout;
    private boolean autoConnect;

    public enum COMMAND_TYPE {
        CMD_NONE,
        CMD_OPEN,
        CMD_CLOSE,
        CMD_QUERY,
        CMD_RFESH
    }

    public void postPrintMsg(int msgType, int iVal, String strVal) {
        if(handler!=null) {
            Message msg = Message.obtain();
            msg.what = msgType;
            Bundle bundle = new Bundle();
            bundle.putInt("code", iVal);
            bundle.putString("message", strVal);
            msg.setData(bundle);
            handler.sendMessage(msg);
        }
    }

    @Override
    public void run() {
        Log.d(MainActivity.TAG, "Client thread running{"+ Thread.currentThread().getId() +"}");
        try {
            while(true) {
                synchronized (waitObject) {
                    waitObject.wait(waitTimeout);
                    switch (commandType) {
                        case CMD_OPEN:
                            boolean ret = connect((String)this.params[0], this.params[1]);
                            postPrintMsg(MessageConst.MSG_OPEN, ret?1:0, printName);
                            if(ret)
                                commandType = COMMAND_TYPE.CMD_QUERY;
                            break;
                        case CMD_CLOSE:
                            ret = close();
                            postPrintMsg(MessageConst.MSG_CLOSE, ret?1:0, printName);
                            commandType = COMMAND_TYPE.CMD_NONE;
                            break;
                        case CMD_QUERY:
                            errorCodes status = getStatus();
                            postPrintMsg(MessageConst.MSG_STATUS, status.getErrCode(), status.toString());
                            if(status.getErrCode()==3 && autoConnect) {
                                close();
                                commandType = COMMAND_TYPE.CMD_OPEN;
                            }
                            break;
                        case CMD_RFESH:
                            commandType = COMMAND_TYPE.CMD_QUERY;
                            break;
                        default: //CMD_NONE
                            break;
                    }
                }
            }
        } catch (InterruptedException e) {
            Log.e(MainActivity.TAG, e.getMessage());
        }
    }

    private PrintJobService(Context context, Handler handler) {
        printApis = new PrintApis(context, handler);
        printApis.CON_SetLogLevel(3);
        objId = 0;
        printName = "";
        printPort = null;
        waitObject = new Object();
        waitTimeout = 5000;
        commandType = COMMAND_TYPE.CMD_NONE;
        autoConnect = true;
    }

    /**
     * Adopt singleton design mode and multithreading completes polling printer state
     * @param context
     * @param handler
     * @return
     */
    public static PrintJobService getObject(Context context, Handler handler) {
        if(printJobService == null) {
            printJobService = new PrintJobService(context, handler);
            printJobService.handler = handler;
            new Thread(printJobService).start();
        }
        return printJobService;
    }

    public ArrayList<String> getSupportPrinters() {
        return printApis.CON_GetSupportPrinters();
    }

    public void doInvoke(COMMAND_TYPE commandType, Object... params) {
        synchronized (waitObject) {
            this.commandType = commandType;
            this.params = params;
            waitObject.notifyAll();
        }
    }

    public boolean connect(String printName, Object printPort) {
        this.printName = printName;
        this.printPort = printPort;
        objId = printApis.CON_ConnectDevices(printName, printPort);
        if(objId>0)
            return true;
        else
            return false;
    }

    public boolean close() {
        if(objId > 0)
            printApis.CON_CloseDevices(objId);
        objId = 0;
        return true;
    }

    public boolean getConnect() {
        if(objId>0)
            return true;
        else
            return false;
    }

    public errorCodes getStatus() {
        if(objId>0)
            return printApis.CON_QueryStatus(objId);
        return errorCodes.ERR_NOT_CONNECT;
    }

    public void printNormal() {
        doInvoke(COMMAND_TYPE.CMD_NONE);
        if(objId>0) {
            printApis.CON_PageStart(objId);
            printApis.ASCII_CtrlReset(objId);
            printApis.ASCII_CtrlAlignType(objId, preDefiniation.AlignType.AT_CENTER);
            printApis.ASCII_PrintString(objId, "*****FONT PRINT TEST*****\n\n", ENCODE);
            printApis.ASCII_CtrlAlignType(objId, preDefiniation.AlignType.AT_LEFT);
            printApis.ASCII_PrintString(objId, 0, 0, 0, 0, "123Normal font正常字体\r\n", ENCODE);
            printApis.ASCII_PrintString(objId, 2, 0, 0, 0, "123Double width倍宽\r\n", ENCODE);
            printApis.ASCII_PrintString(objId, 0, 2, 0, 0, "123Double height倍高\r\n", ENCODE);
            printApis.ASCII_PrintString(objId, 2, 2, 0, 0, "123Double all倍高宽\r\n", ENCODE);
            printApis.ASCII_PrintString(objId, 2, 2, 1, 1, "123All effect所有效果\r\n", ENCODE);
            printApis.ASCII_CtrlFeedLines(objId, 1);
            printApis.ASCII_CtrlAlignType(objId, preDefiniation.AlignType.AT_CENTER);
            printApis.ASCII_PrintString(objId, 0, 0, 0, 0,"*****TEST END*****", ENCODE);
            printApis.ASCII_CtrlFeedLines(objId, 2);
            printApis.ASCII_CtrlAlignType(objId, preDefiniation.AlignType.AT_LEFT);
            printApis.CON_PageEnd(objId);
            printApis.CON_PageSend(objId);
        }
    }

    public void printText(String text) {
        printApis.CON_PageStart(objId);
        printApis.ASCII_PrintString(objId, text, ENCODE);
        printApis.CON_PageEnd(objId);
        printApis.CON_PageSend(objId);
    }

    public void printBuffer(byte []buffer) {
        printApis.ASCII_PrintBuffer(objId, buffer, buffer.length);
    }

    public void printTicket() {
        if(objId==0)
            return;
        printApis.CON_PageStart(objId);
        printApis.ASCII_CtrlReset(objId);
        printApis.ASCII_CtrlAlignType(objId, preDefiniation.AlignType.AT_CENTER);
        printApis.ASCII_PrintString(objId, 1, 2, 0, 0, "兰陵县公益性能产品批发市场\r\n", ENCODE);
        printApis.ASCII_CtrlFeedLines(objId, 1);
        printApis.ASCII_CtrlAlignType(objId, preDefiniation.AlignType.AT_LEFT);
        printApis.ASCII_PrintString(objId, 0, 0, 0, 0, "交易单号：1593441472619456\r\n", ENCODE);
        printApis.ASCII_PrintString(objId, 0, 0, 0, 0, "终端编号：22222\r\n", ENCODE);
        printApis.ASCII_PrintString(objId, 0, 0, 0, 0, "司磅员: sby\r\n", ENCODE);
        printApis.ASCII_PrintString(objId, 0, 0, 0, 0, "菜农名称：sibangyuan\r\n", ENCODE);
        printApis.ASCII_PrintString(objId, 0, 0, 0, 0, "交易单号：1593441472619456\r\n", ENCODE);
        printApis.ASCII_PrintString(objId, 0, 0, 0, 0, "交易单号：1593441472619456\r\n", ENCODE);
        printApis.ASCII_CtrlFeedLines(objId, 2);
        printApis.CON_PageEnd(objId);
        printApis.CON_PageSend(objId);
    }

    public void printCanvas() {
        doInvoke(COMMAND_TYPE.CMD_RFESH);
        printApis.CON_PageStart(objId,500);
        printApis.DRAW_SetLineWidth(objId,2);
        printApis.DRAW_SetFont_BoldMode(objId, preDefiniation.FontBold.NORMAL);
        printApis.DRAW_SetFont_Opposite(objId, false, 0);
        printApis.DRAW_PrintRectangle(objId, 0, 0,  printApis.CON_GetPageWidth(objId), 200);
        printApis.DRAW_PrintText(objId, 40, 40, "Left rotate 90,", 22, 90, Paint.Align.LEFT);
        printApis.DRAW_PrintText(objId,  printApis.CON_GetPageWidth(objId)/2, 40, "Center rotate 180,", 22, 180, Paint.Align.CENTER);
        printApis.DRAW_PrintText(objId,  printApis.CON_GetPageWidth(objId)-40, 30, "Rigth rotate 270,", 22, 270, Paint.Align.RIGHT);
        printApis.DRAW_SetFont_Opposite(objId, true, 10);
        printApis.DRAW_PrintText(objId,  printApis.CON_GetPageWidth(objId)/2, 100, "CENTER", 40, 0, Paint.Align.CENTER);
        printApis.DRAW_Print1D2DBarcode(objId, preDefiniation.BarcodeType.BT_QRcode, 20, 200, 100, 100, "http://www.baidu.com", 90);
        printApis.DRAW_Print1D2DBarcode(objId, preDefiniation.BarcodeType.BT_CODE128, 20, 300, 250, 50, "123456789012", 0);
        printApis.CON_PageEnd(objId);
        printApis.ASCII_CtrlFeedLines(objId, 1);
        printApis.CON_PageSend(objId);
    }

    public void printPicture(Bitmap bitmap, int thresHold) {
        float scale;
        printApis.CON_PageStart(objId,bitmap.getHeight());
        printApis.DRAW_SetPhotoThreshold(objId, thresHold);
        double printWidth = printApis.CON_GetPageWidth(objId);
        scale = (float) (printWidth/bitmap.getWidth());
        printApis.DRAW_PrintPicture(objId, bitmap, 0, 0, scale);
        printApis.CON_PageEnd(objId);
        printApis.ASCII_CtrlFeedLines(objId, 1);
        printApis.CON_PageSend(objId);
    }

    public void print1DBarcode(preDefiniation.BarcodeType barcodeType, int width, int height, preDefiniation.Barcode1DHRI barcode1DHRI, String data) {
        printApis.CON_PageStart(objId);
        printApis.ASCII_Print1DBarcode(objId, barcodeType, width, height, barcode1DHRI, data);
        printApis.CON_PageEnd(objId);
        printApis.ASCII_CtrlFeedLines(objId, 1);
        printApis.CON_PageSend(objId);
    }

    public void print2DBarcode(preDefiniation.BarcodeType barcodeType, int size, int version, int ecc, String data) {
        printApis.CON_PageStart(objId);
        printApis.ASCII_Print2DBarcode(objId, barcodeType, data, version, ecc, size, ENCODE);
        printApis.CON_PageEnd(objId);
        printApis.ASCII_CtrlFeedLines(objId, 1);
        printApis.CON_PageSend(objId);
    }

    public void printLabel() {
        doInvoke(COMMAND_TYPE.CMD_NONE);
        printApis.DRAW_SetMapMode(objId, preDefiniation.MapMode.PIXEL);

        printApis.Label_PageStart(objId, 576, 1500, 0);
        printApis.CON_PageStart(objId,true, 1500, 576);
        printApis.DRAW_SetRotate(objId, 90);
        printApis.DRAW_SetFont_BoldMode(objId, preDefiniation.FontBold.NORMAL);
        printApis.DRAW_SetFont_Opposite(objId, false, 0);

        //标题
        printApis.DRAW_PrintText(objId, 130, 5, "聚盈物流托运单-平兰物流", 45);
        printApis.DRAW_PrintText(objId, 25, 100, "货号：合作191024-兰州2928-1", 24);

        //矩形
        printApis.DRAW_SetLineWidth(objId,4);
        printApis.DRAW_PrintRectangle(objId, 10, 130, 850, 570);
        printApis.DRAW_SetLineWidth(objId,2);
        printApis.DRAW_PrintLine(objId, 10, 170, 850, 170);
        printApis.DRAW_PrintLine(objId, 90, 130, 90, 570);

        //竖向文字
        printApis.DRAW_PrintText(objId, 866, 150, "此", 24);
        printApis.DRAW_PrintText(objId, 866, 180, "单", 24);
        printApis.DRAW_PrintText(objId, 866, 210, "为", 24);
        printApis.DRAW_PrintText(objId, 866, 240, "客", 24);
        printApis.DRAW_PrintText(objId, 866, 270, "户", 24);
        printApis.DRAW_PrintText(objId, 866, 300, "联", 24);
        printApis.DRAW_PrintText(objId, 1100, 110, "保价声明", 24);

        //二维码
        printApis.DRAW_Print1D2DBarcode(objId,
                preDefiniation.BarcodeType.BT_QRcode, 900, 85, 200, 200,
                "http://www.rgprt.com");

        printApis.DRAW_Print1D2DBarcode(objId,
                preDefiniation.BarcodeType.BT_CODE128, 900, 300, 330, 60,
                "1234567890");

        printApis.Label_PageEnd(objId, true);
        printApis.ASCII_CtrlFeedLines(objId, 1);
        printApis.CON_PageSend(objId);
    }

    public void printLabel2() {
        doInvoke(COMMAND_TYPE.CMD_NONE);

        printApis.DRAW_SetMapMode(objId, preDefiniation.MapMode.MM);
        printApis.Label_PageStart(objId, 72, 200, 0);
        printApis.CON_PageStart(objId,true, 200, 72);
        printApis.DRAW_SetRotate(objId, 90);
        printApis.DRAW_SetFont_BoldMode(objId, preDefiniation.FontBold.NORMAL);
        printApis.DRAW_SetFont_Opposite(objId, false, 0);

        //标题
        printApis.DRAW_PrintText(objId, 16.25, 0, "聚盈物流托运单-平兰物流", 6);
        printApis.DRAW_PrintText(objId, 3, 10, "货号：合作191024-兰州2928-1", 4);

        //矩形
        printApis.DRAW_SetLineWidth(objId,0.5);
        printApis.DRAW_PrintRectangle(objId, 1, 16.25, 106.25, 71.5);
        printApis.DRAW_SetLineWidth(objId,0.25);
        printApis.DRAW_PrintLine(objId, 1.25, 21.5, 106.25, 21.5);
        printApis.DRAW_PrintLine(objId, 11, 16, 11, 71.5);
        printApis.DRAW_PrintLine(objId, 1.25, 60, 106.25, 60);

        printApis.DRAW_PrintText(objId, 3, 17, "品名", 3);
        printApis.DRAW_PrintText(objId, 13, 62, "注意：@请参考打印示例", 2);

        //竖向文字
        printApis.DRAW_PrintText(objId, 108.25, 18.75, "此", 3);
        printApis.DRAW_PrintText(objId, 108.25, 22.5, "单", 3);
        printApis.DRAW_PrintText(objId, 108.25, 26.25, "为", 3);
        printApis.DRAW_PrintText(objId, 108.25, 30, "客", 3);
        printApis.DRAW_PrintText(objId, 108.25, 33.75, "户", 3);
        printApis.DRAW_PrintText(objId, 108.25, 37.5, "联", 3);

        //二维码
        printApis.DRAW_Print1D2DBarcode(objId,
                preDefiniation.BarcodeType.BT_QRcode, 112.5, 10.625, 25, 25,
                "http://www.rgprt.com");

        printApis.DRAW_Print1D2DBarcode(objId,
                preDefiniation.BarcodeType.BT_CODE128, 112.5, 37.5, 41.25, 7.5,
                "1234567890");

        printApis.DRAW_SetFont_Opposite(objId, true, 0.4);
        printApis.DRAW_PrintText(objId, 137.5, 13.75, "保价声明", 4.5);
        printApis.DRAW_SetFont_Opposite(objId, false, 0);

        printApis.Label_PageEnd(objId, false);
        printApis.ASCII_CtrlFeedLines(objId, 1);
        printApis.CON_PageSend(objId);
    }

    public void printComplate() {
        doInvoke(COMMAND_TYPE.CMD_QUERY);
    }

    /**
     * Get print job result
     * normal 2000ms; less 1000ms; for a long time 5000
     * @return 0 job status ok; 1 job timeout 2 print offline
     */
    public int getPrintResult() {
        return printApis.CON_QueryJobStatus(objId, 10000);
    }
}
